package schoolsource.model;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.logging.Level;

import schoolsource.sql.SchoolDBSQL;
import schoolsource.util.SchoolLogger;

/**
 *
 * @author Steven Steele
 * Copyright 2004
 *
 * Contains attendance information for a class for a day.
 */
public class ClassAttendance extends Container {

    // The map of timer buckets for all databases
    protected static Hashtable dbStores = new Hashtable();

    // The auto-generated ID of the class in which the homework was assigned.
    private StringItem classID =
        new StringItem(SchoolDBSQL.CLASSASSIGNEDID, "", true);

    // The date absent or tardy.
    private DateNoTimeItem date =
        new DateNoTimeItem(SchoolDBSQL.ATNDDATE, "", true);

    private String dbName;
    private Hashtable attendances;
    private int tardies;
    private int absences;

    /**
     * Default constructor.
     */
    private ClassAttendance() {

    }

    /**
     * Constructor creates a new container filled with values loaded from the database using
     * the class ID, homework ID, and student ID
     * as keys.
     * @param sID The auto-generated student ID.
     * @param cID The auto-generated class ID.
     * @param newDate The date of attendance. This should be formatted in the mm/dd/yyyy format.
     * @dbName The database of the school where the query should be performed.
     */
    private ClassAttendance(String cID, String newDate, String dbName) {
        this.dbName = dbName;
        getClassID().setValue(cID);
        getDate().setValue(newDate);
        attendances = SchoolDBSQL.getSchoolDBSQL(dbName).loadClassAttendance(
            getClassID(),
            getDate());
        count();
    }

    public static ClassAttendance getClassAttendance(String cID, String date, String dbName) {
        ClassAttendance returnVal = null;
//        DBStore dbs = null;

//        if ((dbs = (DBStore) dbStores.get(dbName)) == null) {
//            dbs = new DBStore();
//            dbStores.put(dbName, dbs);
//            dbs.start();
//        }

//        if ((returnVal = (ClassAttendance) dbs.getContainer("C" + cID + "D" + date)) == null) {
            returnVal = new ClassAttendance(cID, date, dbName);
//            returnVal.dbName = dbName;
//            dbs.addContainer(returnVal, "C" + cID + "D" + date);
//        }

        return returnVal;
    }

    /**
     *
     */
    public Item[] getValidationItems() {
        return null;
    }

    /**
     *
     * @return The AttendanceContainer for the specified student. Returns null if there is not record for the student.
     */
     // TODO This function provides access to changing the attendance container. This can get get things out of sync. Fix it
    public AttendanceContainer getStudentAttendance(String studentID) {
        return (AttendanceContainer) attendances.get(studentID);
    }

    /**
     *
     *
     *
     */
    synchronized public void updateAttendance(String studentID, String absenceType) {
        AttendanceContainer storedValue = getStudentAttendance(studentID);
        AttendanceContainer inputValue = AttendanceContainer.getAttendanceContainer(studentID, getClassID().toString(), getDate().toString(), dbName);
        if (storedValue == null) {
            if ("ABSENT".equals(absenceType) ||
                "TARDY".equals(absenceType)) {
                inputValue.getType().setValue(absenceType);
                attendances.put(studentID, inputValue);
                SchoolDBSQL.getSchoolDBSQL(dbName).save(inputValue);
            }
            // else nothing is done
        }
        else {
            if (storedValue.getType() != null && inputValue.getType() != null &&
                !storedValue.getType().toString().equals(inputValue.getType().toString())) {
                storedValue.getType().setValue(inputValue.getType().toString());
                if ("".equals(storedValue.getType().toString())) {
                    SchoolDBSQL.getSchoolDBSQL(dbName).deleteAttendance(inputValue.getStudentID(), inputValue.getClassID(), inputValue.getDate());
                    attendances.remove(studentID);  // TODO the object should be able to delete itself from AttendanceContainer
                }
                else {
                    SchoolDBSQL.getSchoolDBSQL(dbName).save(storedValue);
                }
            }
        }
    }

    /**
     * Getter for the class ID of the attendance.
     * @return The auto-generated ID of the class for which this attendance applies.
     */
    public StringItem getClassID() {
        return classID;
    }

    /**
     * Getter for the date.
     * @return The date.
     */
    public DateNoTimeItem getDate() {
        return date;
    }

    /**
     *
     *
     *
     */
    synchronized private void count() {
        tardies = 0;
        absences = 0;
        Enumeration attendance = attendances.elements();
        AttendanceContainer ac;
        while (attendance.hasMoreElements()) {
            ac = (AttendanceContainer) attendance.nextElement();
            if ("ABSENT".equals(ac.getType().toString())) {
                ++absences;
            }
            else if ("TARDY".equals(ac.getType().toString())) {
                ++tardies;
            }
        }
    }

    synchronized public int getTotalTardies() {
        count();
        return tardies;
    }

    synchronized public int getTotalAbsences() {
        count();
        return absences;
    }


    /**
     * Prints the values of the container.
     */
    public void printItems() {
        SchoolLogger.logger.log(
            Level.INFO,
            "************************************************");
        Item iList[] = getValidationItems();
        for (int j = 0; j < iList.length; j++) {
            if (iList[j] != null) {
                SchoolLogger.logger.log(
                    Level.INFO,
                    iList[j].getFieldName() + ": " + iList[j].toString());
            }
        }
    }
}
